import { useEffect, useMemo, useState } from 'react';
import {
  Alert,
  Image,
  KeyboardAvoidingView,
  Modal,
  Platform,
  Pressable,
  ScrollView,
  StyleSheet,
  TextInput,
  View,
} from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import { ResizeMode, Video } from 'expo-av';
import { useLocalSearchParams, useRouter } from 'expo-router';

import { ThemedButton } from '@/components/themed-button';
import { IconButton } from '@/components/icon-button';
import { ThemedText } from '@/components/themed-text';
import { ThemedView } from '@/components/themed-view';
import { ZoomImageModal } from '@/components/zoom-image-modal';
import { Colors } from '@/constants/theme';
import { useColorScheme } from '@/hooks/use-color-scheme';
import { useTranslation } from '@/localization/i18n';
import { dbPromise, initCoreTables } from '@/services/db';

type FieldRow = {
  id: number;
  name: string | null;
};

type CropRow = {
  id: number;
  crop_name: string | null;
};

type ObservationRow = {
  id: number;
  field_id: number | null;
  crop_id: number | null;
  obs_type: string | null;
  note: string | null;
  severity: number | null;
  observed_at: string | null;
};

type ImageRow = {
  uri: string | null;
};

export default function ObservationDetailScreen() {
  const { t } = useTranslation();
  const router = useRouter();
  const { id } = useLocalSearchParams<{ id?: string | string[] }>();
  const observationId = Number(Array.isArray(id) ? id[0] : id);
  const theme = useColorScheme() ?? 'light';
  const palette = Colors[theme];

  const [loading, setLoading] = useState(true);
  const [status, setStatus] = useState('');
  const [fields, setFields] = useState<FieldRow[]>([]);
  const [crops, setCrops] = useState<CropRow[]>([]);
  const [fieldModalOpen, setFieldModalOpen] = useState(false);
  const [cropModalOpen, setCropModalOpen] = useState(false);
  const [selectedFieldId, setSelectedFieldId] = useState<number | null>(null);
  const [selectedCropId, setSelectedCropId] = useState<number | null>(null);
  const [type, setType] = useState('');
  const [severity, setSeverity] = useState('');
  const [note, setNote] = useState('');
  const [mediaUris, setMediaUris] = useState<string[]>([]);
  const [activeUri, setActiveUri] = useState<string | null>(null);
  const [errors, setErrors] = useState<{ field?: string; severity?: string }>({});
  const [zoomUri, setZoomUri] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);
  const [showSaved, setShowSaved] = useState(false);

  useEffect(() => {
    let isActive = true;

    async function loadObservation() {
      try {
        await initCoreTables();
        const db = await dbPromise;
        const fieldRows = await db.getAllAsync<FieldRow>('SELECT id, name FROM fields ORDER BY name ASC;');
        const cropRows = await db.getAllAsync<CropRow>('SELECT id, crop_name FROM crops ORDER BY crop_name ASC;');
        const obsRows = await db.getAllAsync<ObservationRow>(
          'SELECT id, field_id, crop_id, obs_type, note, severity, observed_at FROM observations WHERE id = ? LIMIT 1;',
          observationId
        );
        if (!isActive) return;
        setFields(fieldRows);
        setCrops(cropRows);
        const obs = obsRows[0];
        if (!obs) {
          setStatus(t('observations.empty'));
          setLoading(false);
          return;
        }
        setSelectedFieldId(obs.field_id ?? null);
        setSelectedCropId(obs.crop_id ?? null);
        setType(obs.obs_type ?? '');
        setSeverity(obs.severity !== null ? String(obs.severity) : '');
        setNote(obs.note ?? '');
        const imageRows = await db.getAllAsync<ImageRow>(
          'SELECT uri FROM images WHERE observation_id = ? ORDER BY created_at ASC;',
          observationId
        );
        const media = uniqueMediaUris(imageRows.map((row) => row.uri).filter(Boolean) as string[]);
        setMediaUris(media);
        setActiveUri(media[0] ?? null);
      } catch (error) {
        if (isActive) setStatus(`Error: ${String(error)}`);
      } finally {
        if (isActive) setLoading(false);
      }
    }

    loadObservation();
    return () => {
      isActive = false;
    };
  }, [observationId, t]);

  const selectedField = useMemo(
    () => fields.find((item) => item.id === selectedFieldId),
    [fields, selectedFieldId]
  );
  const selectedCrop = useMemo(
    () => crops.find((item) => item.id === selectedCropId),
    [crops, selectedCropId]
  );

  const inputStyle = [
    styles.input,
    {
      borderColor: palette.border,
      backgroundColor: palette.input,
      color: palette.text,
    },
  ];
  const typePresets = ['scouting', 'pest', 'disease', 'weeds', 'nutrients', 'irrigation'];

  async function handleUpdate() {
    const parsedSeverity = severity.trim() ? Number(severity) : null;
    const nextErrors: { field?: string; severity?: string } = {};
    if (!selectedFieldId) {
      nextErrors.field = t('observations.fieldRequired');
    }
    if (severity.trim() && !Number.isFinite(parsedSeverity)) {
      nextErrors.severity = t('observations.severityInvalid');
    }
    setErrors(nextErrors);
    if (Object.keys(nextErrors).length > 0) return;
    try {
      setSaving(true);
      const db = await dbPromise;
      await db.runAsync(
        'UPDATE observations SET field_id = ?, crop_id = ?, obs_type = ?, note = ?, severity = ? WHERE id = ?;',
        selectedFieldId,
        selectedCropId,
        type.trim() || null,
        note.trim() || null,
        parsedSeverity,
        observationId
      );
      await db.runAsync('DELETE FROM images WHERE observation_id = ?;', observationId);
      const now = new Date().toISOString();
      for (const uri of uniqueMediaUris(mediaUris)) {
        await db.runAsync(
          'INSERT INTO images (observation_id, uri, created_at) VALUES (?, ?, ?);',
          observationId,
          uri,
          now
        );
      }
      setStatus(t('observations.saved'));
      setShowSaved(true);
      setTimeout(() => {
        setShowSaved(false);
        setStatus('');
      }, 1800);
    } catch (error) {
      setStatus(`Error: ${String(error)}`);
    } finally {
      setSaving(false);
    }
  }

  function confirmDelete() {
    Alert.alert(
      t('observations.deleteTitle'),
      t('observations.deleteMessage'),
      [
        { text: t('observations.cancel'), style: 'cancel' },
        {
          text: t('observations.delete'),
          style: 'destructive',
          onPress: async () => {
            const db = await dbPromise;
            await db.runAsync('DELETE FROM images WHERE observation_id = ?;', observationId);
            await db.runAsync('DELETE FROM observations WHERE id = ?;', observationId);
            router.back();
          },
        },
      ]
    );
  }

  if (loading) {
    return (
      <ThemedView style={[styles.container, { backgroundColor: palette.background }]}>
        <ThemedText>{t('observations.loading')}</ThemedText>
      </ThemedView>
    );
  }

  return (
    <ThemedView style={[styles.container, { backgroundColor: palette.background }]}>
      <KeyboardAvoidingView
        behavior={Platform.OS === 'ios' ? 'padding' : undefined}
        style={styles.keyboardAvoid}>
        <ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps="handled">
          <ThemedText type="title">{t('observations.edit')}</ThemedText>
          {status && !showSaved ? <ThemedText>{status}</ThemedText> : null}

          <ThemedText>{t('observations.field')}</ThemedText>
          <ThemedButton
            title={selectedField?.name || t('observations.selectField')}
            onPress={() => setFieldModalOpen(true)}
            variant="secondary"
          />
          {errors.field ? <ThemedText style={styles.errorText}>{errors.field}</ThemedText> : null}

          <ThemedText>{t('observations.crop')}</ThemedText>
          <ThemedButton
            title={selectedCrop?.crop_name || t('observations.selectCrop')}
            onPress={() => setCropModalOpen(true)}
            variant="secondary"
          />

          <ThemedText>{t('observations.type')}</ThemedText>
          <View style={styles.chipRow}>
            {typePresets.map((preset) => {
              const label = t(`observations.type.${preset}`);
              const isActive = type === label || type === preset;
              return (
                <Pressable
                  key={preset}
                  style={[styles.chip, isActive ? styles.chipActive : null]}
                  onPress={() => setType(label)}>
                  <ThemedText style={styles.chipText}>{label}</ThemedText>
                </Pressable>
              );
            })}
          </View>
          <TextInput
            value={type}
            onChangeText={setType}
            placeholder={t('observations.typePlaceholder')}
            placeholderTextColor={palette.placeholder}
            style={inputStyle}
          />

          <ThemedText>{t('observations.severity')}</ThemedText>
          <TextInput
            value={severity}
            onChangeText={(value) => {
              setSeverity(value);
              if (errors.severity) setErrors((prev) => ({ ...prev, severity: undefined }));
            }}
            placeholder={t('observations.severityPlaceholder')}
            placeholderTextColor={palette.placeholder}
            style={inputStyle}
            keyboardType="decimal-pad"
          />
          {errors.severity ? <ThemedText style={styles.errorText}>{errors.severity}</ThemedText> : null}

          <ThemedText>{t('observations.note')}</ThemedText>
          <TextInput
            value={note}
            onChangeText={setNote}
            placeholder={t('observations.notePlaceholder')}
            placeholderTextColor={palette.placeholder}
            style={inputStyle}
            multiline
          />

          <ThemedText>{t('observations.addMedia')}</ThemedText>
          {normalizeMediaUri(activeUri) ? (
            isVideoUri(normalizeMediaUri(activeUri) as string) ? (
              <Video
                source={{ uri: normalizeMediaUri(activeUri) as string }}
                style={styles.mediaPreview}
                useNativeControls
                resizeMode={ResizeMode.CONTAIN}
              />
            ) : (
              <Pressable onPress={() => setZoomUri(normalizeMediaUri(activeUri) as string)}>
                <Image source={{ uri: normalizeMediaUri(activeUri) as string }} style={styles.mediaPreview} resizeMode="contain" />
              </Pressable>
            )
          ) : (
            <ThemedText style={styles.photoPlaceholder}>{t('observations.noPhoto')}</ThemedText>
          )}

          {mediaUris.length > 0 ? (
            <ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.mediaStrip}>
              {mediaUris.map((uri) => (
                <Pressable key={uri} style={styles.mediaChip} onPress={() => setActiveUri(uri)}>
                  {isVideoUri(uri) ? (
                    <View style={styles.videoThumb}>
                      <ThemedText style={styles.videoThumbText}>▶</ThemedText>
                    </View>
                  ) : (
                    <Image source={{ uri }} style={styles.mediaThumb} resizeMode="cover" />
                  )}
                  <Pressable
                    style={styles.mediaRemove}
                    onPress={(event) => {
                      event.stopPropagation();
                      setMediaUris((prev) => {
                        const next = prev.filter((item) => item !== uri);
                        setActiveUri((current) => (current === uri ? next[0] ?? null : current));
                        return next;
                      });
                    }}>
                    <ThemedText style={styles.mediaRemoveText}>×</ThemedText>
                  </Pressable>
                </Pressable>
              ))}
            </ScrollView>
          ) : null}

          <View style={styles.photoRow}>
            <ThemedButton
              title={t('observations.pickFromGallery')}
              onPress={() =>
                handlePickMedia((uris) => {
                  if (uris.length === 0) return;
                  setMediaUris((prev) => uniqueMediaUris([...prev, ...uris]));
                  setActiveUri((prev) => prev ?? uris[0]);
                })
              }
              variant="secondary"
            />
            <ThemedButton
              title={t('observations.takeMedia')}
              onPress={() =>
                handleTakeMedia((uri) => {
                  if (!uri) return;
                  setMediaUris((prev) => uniqueMediaUris([...prev, uri]));
                  setActiveUri((prev) => prev ?? uri);
                })
              }
              variant="secondary"
            />
          </View>

          <View style={styles.actions}>
            <IconButton
              name="trash"
              onPress={confirmDelete}
              accessibilityLabel={t('observations.delete')}
              variant="danger"
            />
            <View style={styles.updateGroup}>
              {showSaved ? <ThemedText style={[styles.inlineToastText, { color: palette.success }]}>{t('observations.saved')}</ThemedText> : null}
              <ThemedButton
                title={saving ? t('observations.saving') : t('observations.update')}
                onPress={handleUpdate}
                disabled={saving}
              />
            </View>
          </View>
        </ScrollView>
      </KeyboardAvoidingView>

      <Modal transparent visible={fieldModalOpen} animationType="fade">
        <Pressable style={styles.modalBackdrop} onPress={() => setFieldModalOpen(false)}>
          <View style={styles.modalCard}>
            <ThemedText type="subtitle">{t('observations.selectField')}</ThemedText>
            <ScrollView style={styles.modalList}>
              {fields.map((item) => (
                <Pressable
                  key={item.id}
                  style={styles.modalItem}
                  onPress={() => {
                    setSelectedFieldId(item.id);
                    setFieldModalOpen(false);
                  }}>
                  <ThemedText>{item.name || t('observations.untitled')}</ThemedText>
                </Pressable>
              ))}
            </ScrollView>
          </View>
        </Pressable>
      </Modal>

      <Modal transparent visible={cropModalOpen} animationType="fade">
        <Pressable style={styles.modalBackdrop} onPress={() => setCropModalOpen(false)}>
          <View style={styles.modalCard}>
            <ThemedText type="subtitle">{t('observations.selectCrop')}</ThemedText>
            <ScrollView style={styles.modalList}>
              {crops.map((item) => (
                <Pressable
                  key={item.id}
                  style={styles.modalItem}
                  onPress={() => {
                    setSelectedCropId(item.id);
                    setCropModalOpen(false);
                  }}>
                  <ThemedText>{item.crop_name || t('observations.untitled')}</ThemedText>
                </Pressable>
              ))}
            </ScrollView>
          </View>
        </Pressable>
      </Modal>

      <ZoomImageModal uri={zoomUri} visible={Boolean(zoomUri)} onClose={() => setZoomUri(null)} />
    </ThemedView>
  );
}

async function handlePickMedia(onAdd: (uris: string[]) => void) {
  const result = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: getMediaTypes(),
    quality: 1,
    allowsMultipleSelection: true,
    selectionLimit: 0,
  });
  if (result.canceled) return;
  const uris = (result.assets ?? []).map((asset) => asset.uri).filter(Boolean) as string[];
  if (uris.length === 0) return;
  onAdd(uris);
}

async function handleTakeMedia(onAdd: (uri: string | null) => void) {
  const permission = await ImagePicker.requestCameraPermissionsAsync();
  if (!permission.granted) {
    return;
  }
  const result = await ImagePicker.launchCameraAsync({
    mediaTypes: getMediaTypes(),
    quality: 1,
  });
  if (result.canceled) return;
  const asset = result.assets[0];
  onAdd(asset.uri);
}

function getMediaTypes() {
  const mediaType = (ImagePicker as {
    MediaType?: { Image?: unknown; Images?: unknown; Video?: unknown; Videos?: unknown };
  }).MediaType;
  const imageType = mediaType?.Image ?? mediaType?.Images;
  const videoType = mediaType?.Video ?? mediaType?.Videos;
  if (imageType && videoType) {
    return [imageType, videoType];
  }
  return imageType ?? videoType ?? ['images', 'videos'];
}

function isVideoUri(uri: string) {
  return /\.(mp4|mov|m4v|webm|avi|mkv)(\?.*)?$/i.test(uri);
}

function normalizeMediaUri(uri?: string | null) {
  if (typeof uri !== 'string') return null;
  const trimmed = uri.trim();
  return trimmed ? trimmed : null;
}

function uniqueMediaUris(uris: string[]) {
  const seen = new Set<string>();
  const result: string[] = [];
  for (const uri of uris) {
    if (!uri || seen.has(uri)) continue;
    seen.add(uri);
    result.push(uri);
  }
  return result;
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  keyboardAvoid: {
    flex: 1,
  },
  content: {
    padding: 16,
    gap: 10,
    paddingBottom: 40,
  },
  input: {
    borderRadius: 10,
    borderWidth: 1,
    paddingHorizontal: 12,
    paddingVertical: 10,
    fontSize: 15,
  },
  errorText: {
    color: '#C0392B',
    fontSize: 12,
  },
  mediaPreview: {
    width: '100%',
    height: 220,
    borderRadius: 12,
    backgroundColor: '#1C1C1C',
  },
  photoRow: {
    flexDirection: 'row',
    gap: 8,
  },
  actions: {
    marginTop: 12,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    gap: 10,
  },
  photoPlaceholder: {
    opacity: 0.6,
  },
  mediaStrip: {
    marginTop: 6,
  },
  mediaChip: {
    width: 72,
    height: 72,
    borderRadius: 10,
    marginRight: 8,
    overflow: 'hidden',
    backgroundColor: '#E6E1D4',
    alignItems: 'center',
    justifyContent: 'center',
  },
  mediaThumb: {
    width: '100%',
    height: '100%',
  },
  videoThumb: {
    width: '100%',
    height: '100%',
    backgroundColor: '#1C1C1C',
    alignItems: 'center',
    justifyContent: 'center',
  },
  videoThumbText: {
    color: '#FFFFFF',
    fontSize: 18,
    fontWeight: '700',
  },
  mediaRemove: {
    position: 'absolute',
    top: 4,
    right: 4,
    width: 18,
    height: 18,
    borderRadius: 9,
    backgroundColor: 'rgba(0,0,0,0.6)',
    alignItems: 'center',
    justifyContent: 'center',
  },
  mediaRemoveText: {
    color: '#FFFFFF',
    fontSize: 12,
    lineHeight: 14,
    fontWeight: '700',
  },
  updateGroup: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 8,
  },
  inlineToastText: {
    fontWeight: '700',
    fontSize: 12,
  },
  chipRow: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    gap: 8,
    marginBottom: 8,
  },
  chip: {
    paddingHorizontal: 12,
    paddingVertical: 6,
    borderRadius: 999,
    borderWidth: 1,
    borderColor: '#D9D1C2',
    backgroundColor: '#F8F6F0',
  },
  chipActive: {
    backgroundColor: '#DDE8DA',
    borderColor: '#88A68F',
  },
  chipText: {
    fontSize: 13,
  },
  modalBackdrop: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.4)',
    justifyContent: 'center',
    padding: 24,
  },
  modalCard: {
    borderRadius: 14,
    backgroundColor: '#FFFFFF',
    padding: 16,
    gap: 10,
    maxHeight: '80%',
  },
  modalList: {
    maxHeight: 300,
  },
  modalItem: {
    paddingVertical: 10,
  },
});
